<template>
  <div class="search-bar">
    <form ref="form" @submit.prevent="handleSubmit">
      <el-row>
        <el-col
          style="float:right;text-align:right;white-space:nowrap"
          v-bind="responsive"
        >
          <div class="search-bar__item" style="justify-content:flex-end">
            <el-button style="color:#444" @click="onReset">
              <i class="el-icon-s search-bar__redo search-bar__filter"></i>重置
            </el-button>
            <el-button type="primary" @click="$emit('search')">
              <i class="el-icon-s search-bar__filter"></i>查询
            </el-button>
            <el-button
              v-if="needExpand"
              type="text"
              @click.native="toggleExpand"
              >{{ isExpand ? '收起' : '展开' }}
              <i
                class="el-icon-arrow-down"
                :style="{
                  transform: `rotate(${isExpand ? 180 : 0}deg)`,
                  display: 'inline-block'
                }"
              ></i
            ></el-button>
          </div>
        </el-col>
        <el-col
          v-for="c in controls"
          :key="c.title"
          v-bind="getColResponsive(c.colspan || 1)"
        >
          <Control v-bind="c" v-model="data[c.name]" @enter="onEnter" />
        </el-col>

        <!-- <el-col :span="6">
            <el-button icon="el-icon-refresh-left">重置</el-button>
            <el-button type="primary">查询</el-button>
            <el-button type="text" @click.native="toggleExpand"
              >展开 <i class="el-icon-arrow-down"></i
            ></el-button>
          </el-col> -->
      </el-row>
    </form>
  </div>
</template>
<script lang="ts">
import { Component, Vue, Watch, Prop } from 'vue-property-decorator'
import Control from './control'
import engine from '../.././utils/engine'

const DEFAULT_HEIGHT = 44
const easing = (t: number) => Math.sin((t * Math.PI) / 2)

// 搜索项接口
type SearchControl = {
  title: string
  // 原生name属性
  name?: string
  props?: any
  value?: any
  colspan?: number
}

function updateData(data: any, value: any) {
  if (!value) {
    return
  }

  for (const k in value) {
    Vue.set(data, k, value[k])
  }
}

@Component({
  name: 'SearchBar',
  components: { Control }
})
export default class index extends Vue {
  // 搜索项配置
  @Prop({ default: () => {} }) controls?: SearchControl[]
  // 是否显示重置按钮
  @Prop({ default: true }) showReset?: boolean
  // 在input上按enter时，是否触发搜索
  @Prop({ default: true }) loadOnEnter?: boolean
  // 用于双向绑定
  @Prop({ default: () => ({}) }) value?: object

  @Prop() loadOnReset?: Boolean
  @Prop() valueFormat?: (val: any) => any

  // 表单数据
  data: any = {}
  // 是否展开
  isExpand = false
  // 是否需要展开按钮
  needExpand = true

  // 响应式配置
  responsive = {
    xs: 12,
    sm: 8,
    md: 8,
    lg: 6,
    xl: 4
  }

  getColResponsive(colspan: number) {
    const obj: any = {}
    for (const [key, val] of Object.entries(this.responsive)) {
      obj[key] = val * colspan
    }
    return obj
  }
  mounted() {
    let tid = 0
    const resize = () => {
      clearTimeout(tid)
      tid = setTimeout(() => {
        const height = this.computeHeight()
        if (this.isExpand) {
          // @ts-ignore
          this.$refs.form.style.height = height + 'px'
        }
      }, 100) as any
    }
    window.addEventListener('resize', resize)
    this.$once('hook:beforeDestroy', () => {
      window.removeEventListener('resize', resize)
    })
    this.$nextTick(() => {
      this.computeHeight()
    })
    this.setDefaultValue()
  }

  setDefaultValue() {
    this.controls &&
      this.controls.forEach(c => {
        typeof c.value !== 'undefined' &&
          c.name &&
          this.$set(this.data, c.name, c.value)
      })
  }

  @Watch('data', {
    deep: true
  })
  onDataChange() {
    this.$emit(
      'input',
      this.valueFormat ? this.valueFormat(this.data) : this.data
    )
  }
  // 计算高度
  computeHeight() {
    const el: HTMLFormElement = this.$refs.form as HTMLFormElement
    el.style.height = 'auto'
    // fit margin
    const height = el.clientHeight
    el.__height__ = height
    this.needExpand = height > DEFAULT_HEIGHT
    el.style.height = ''
    return height
  }

  // 动画transition组件不方便控制，用JS代替
  toggleExpand() {
    const el: HTMLFormElement = this.$refs.form as HTMLFormElement
    if (this.isExpand) {
      const { __height__ } = el
      __height__ &&
        engine(
          200,
          (p: number) => {
            el.style.height =
              __height__ - (__height__ - DEFAULT_HEIGHT) * p + 'px'
          },
          easing
        ).then(() => {
          this.isExpand = false
        })
    } else {
      const height = this.computeHeight()
      engine(
        200,
        (p: number) => {
          el.style.height =
            DEFAULT_HEIGHT + (height - DEFAULT_HEIGHT) * p + 'px'
        },
        easing
      ).then(() => {
        this.isExpand = true
      })
    }
  }
  onReset() {
    const obj: any = {}
    for (let k in this.data) {
      obj[k] = ''
    }
    this.data = obj
    this.$emit('reset')

    // FIXME:删除重置操作需要刷新数据
    this.loadOnReset &&
      this.$nextTick(() => {
        this.$emit('search')
      })
  }
  onEnter() {
    this.loadOnEnter && this.$emit('search')
  }
  created() {
    updateData(this.data, this.value)
  }
  handleSubmit() {}
}
</script>
<style lang="scss">
.search-bar {
  padding: 12px;
  background: #fff;
  form {
    height: 44px;
    overflow: hidden;
    margin: -6px -8px;
  }
  @at-root &__filter {
    display: inline-block;
    width: 14px;
    height: 14px;
    background: url(../../assets/filter.png) no-repeat center;
    background-size: contain;
    vertical-align: bottom;
    margin-right: 5px;
  }
  @at-root &__redo {
    background-image: url(../../assets/redo.png);
  }
  @at-root &__item {
    padding: 6px 8px;
    display: flex;
    align-items: center;
    box-sizing: content-box;
    // element default height
    height: 32px;
  }
  @at-root &__item-label {
    color: #999999;
    margin-right: 24px;
  }
  @at-root &__more {
    [class$='item'] {
      margin-top: 10px;
    }
  }
}
</style>
